#include "engine.h"
#include "scene.h"

using namespace std;

Engine *Engine::instance=NULL;

Engine::Engine(){
	exit=false;
}



Engine &Engine::GetEngine(){

	if(!instance)
	{
		instance= new Engine();
	}
	return *instance;
}



void Engine::Init(unsigned w, unsigned h){

	window.Create(sf::VideoMode(w,h,32),"QRS Complex");
	window.SetFramerateLimit(60);
	currentScene=NULL;
	sceneToDelete=NULL;

}



void Engine::Loop(){

	sf::Clock clock;
	float elapsedTime;
	sf::Event event;

	clock.Reset();

	while(!exit && currentScene!=NULL)
	{
		elapsedTime=clock.GetElapsedTime();
		clock.Reset();		

		
		//Procesa eventos
		while(window.GetEvent(event))
		{
			if(event.Type==event.Closed)
			{
				window.Close();
				exit=true;
			}
			else
			{
				currentScene->ProcessEvent(event);
			}
		}
		
	
		//Actualiza la escena actual
		currentScene->Update(elapsedTime);
	
		//Dibuja
		currentScene->Render(window);
		window.Display();
		
		//Realiza el cambio de escena, si se requiere
		if(mustUpdateCurrentScene)
		{
			//Si hay una escena por eliminar
			if(sceneToDelete != NULL)		
			{
				sceneToDelete->CleanUp();
				delete sceneToDelete;
				sceneToDelete=NULL;
			}
			

			//La escena actual es la que está al frente de la cola
			if(sceneQueue.size()>0)
			{
				currentScene=sceneQueue.front();
			}
			else
			{	
				currentScene=NULL;
			}
		}
	}
}



void Engine::ChangeScene(Scene *s){
	PopScene();//Quita la actual;
	PushScene(s);//Coloca otra escena en su posición;
	mustUpdateCurrentScene=true;//Indica que se debe realizar el cambio
}


void Engine::PushScene(Scene *s){
	s->Init();
	sceneQueue.push_front(s);//se carga al incio de la cola
	mustUpdateCurrentScene=true;
	sceneToDelete=NULL;//NO se debe borrar la actual, queda suspendida
}


void Engine::AppendScene(Scene *s){
	if(sceneQueue.size()==0)
		currentScene=s;
	sceneQueue.push_back(s);
	s->Init();
	sceneToDelete=NULL;	
}


void Engine::PopScene(){
	sceneToDelete=sceneQueue.front();
	sceneQueue.pop_front();
	mustUpdateCurrentScene=true;	
}


void Engine::EndCurrentScene(){
	PopScene();
}




const sf::Input &Engine::GetInput() const{
	return window.GetInput();
}

sf::RenderWindow &Engine::GetRenderWindow(){
	return window;
}


void  Engine::Exit(){
	exit=true;
}
















